﻿
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#pragma once

#include "Color.h"
#include "WeakPtr.h"
#include "ElementId.h"
#include "UniIdentity.h"

#include <QComboBox>
#include <functional>
#include <QTableWidget>
#include "QButtonGroup"
#include "IGraphicsStyleData.h"

/// 本文件是界面实现的辅助类，仅包含非常少的GDMP API的演示内容

namespace QT_NAMESPACE { class QComboBox; }

typedef UInt64 WndId;
namespace gcmp
{
    class IUiView;
    class IDocument;
    class ICategory;
    class IModelView;
    class IUiDocument;
    class IGraphicsStyle;
    class IGraphicsStyleDataValiditySettings;
    class IGraphicsStyleDataOverrideItems;
}

namespace Sample
{
    class GraphicsStyleDlg;
    struct GraphicsOverrideData;

    // 【显示样式探针】和【节点树样式探针】打开对话框中的表格
    // 本表格会根据TableType参数初始化和显示不同的显示样式内容，对应对话框Tab中的不同表格
    class GraphicsStyleTable : public QWidget
    {
        Q_OBJECT
    public:
        enum class TableType
        {
            ProjectionSectionLines,
            ProjectionSectionFaces,
        };

        GraphicsStyleTable(gcmp::IUiDocument * pUIDoc, gcmp::IUiView * currentView,
            QDialog * parent, TableType tableType, std::vector<gcmp::OwnerPtr<GraphicsOverrideData>>& gOverrideDataList);
        virtual QWidget* GetWidgetFW() { return m_table; }

    public:
        virtual void OnApplied();
    private:
        private slots:
        // 点击表格中修改颜色的按钮
        void OnClickColorCell(int bnt);
        // 点击表格中修改线型的按钮
        void OnClickLineTypeCell(int iButtonIndex);

    private:
        // 初始化【投影和截面线样式】表格
        void initLines();
        // 初始化【投影和截面面样式】表格
        void initFaces();

    private:
        TableType m_tableType;
        
        // 下面是对IGraphicsStyleData中get/set函数的回调函数类，从而可以用数据的方式初始化和使用get/set函数 
        typedef std::function<double(int)> GetDoubleFunc;
        typedef std::function<void(int, double)> SetDoubleFunc;
        typedef std::function<gcmp::Color(int)> GetColorFunc;
        typedef std::function<void(int, gcmp::Color)> SetColorFunc;
        typedef std::function<bool(int)> GetBoolFunc;
        typedef std::function<void(int, bool)> SetBoolFunc;
        typedef std::function<std::wstring(int)> GetTextFunc;
        typedef std::function<void(int, std::wstring)> SetTextFunc;

        struct OverrideFunc
        {
        public:
            GetBoolFunc m_getOverrideFunc;
            SetBoolFunc m_setOverrideFunc;
            bool m_canOverride;

            OverrideFunc(GetBoolFunc getFunc, SetBoolFunc setFunc, bool canOverride = true)
                : m_getOverrideFunc(getFunc), m_setOverrideFunc(setFunc), m_canOverride(canOverride)
            {};

            OverrideFunc() {};
        };

        template <typename FuncType>
        class FunctionHolder {
        public:
            FunctionHolder(FuncType func, OverrideFunc overrideFunc) : m_function(func), m_overrideFunc(overrideFunc) {}
            FuncType m_function;
            OverrideFunc m_overrideFunc;
        };

        typedef std::vector<OverrideFunc> OverrideFuncList;
        typedef std::vector<OverrideFuncList> OverrideFuncListList;

        typedef std::pair<int, int> UVIndex;
        std::map<UVIndex, QVariant> m_setFuncDict;
    
    private:
        // 设置表格cell不可用
        void MakeCellDisable(int row, int column);
        // 根据IsAvailable对行数据的判断，设置每个Cell的可用性
        bool UpdateAvailableStatus(int row, int column);
        bool IsAvailable(int row);

        // 显示样式是否重载的checkbox
        void ShowOverrideCell(int row, int column, OverrideFunc overrideFunc);
        bool GetOverrideCell(int row, int column);

        // 线宽两列的显示：线宽的重载checkbox和线宽
        void ShowLineWidthCell(GetDoubleFunc func, SetDoubleFunc setFunc, OverrideFunc overrideFunc, int row, int column);
        // 线宽两列的设置：线宽的重载checkbox和线宽
        void SetLineWidthCell(int row, int column);
        // 颜色两列的显示：颜色的重载checkbox和颜色
        void ShowColorCell(GetColorFunc func, SetColorFunc setFunc, OverrideFunc overrideFunc, int row, int column);
        // 颜色两列的设置：颜色的重载checkbox和颜色
        void SetColorCell(int row, int column);
        // 线型两列的显示：线型的重载checkbox和线型
        void ShowLineTypeCell(GetTextFunc func, SetTextFunc setFunc, OverrideFunc overrideFunc, int row, int column);
        // 线型两列的设置：线型的重载checkbox和线型
        void SetLineTypeCell(int row, int column);
        // 布尔值两列的显示：线型的重载checkbox和布尔值
        void ShowEnabledCell(GetBoolFunc func, SetBoolFunc setFunc, OverrideFunc overrideFunc, int row, int column);
        // 布尔值两列的设置：线型的重载checkbox和布尔值
        void SetEnabledCell(int row, int column);
        // 填充样式两列的显示：填充样式的重载checkbox和填充样式
        void ShowHatchPatternCell(GetTextFunc func, SetTextFunc setFunc, OverrideFunc overrideFunc, int row, int column);
        // 填充样式两列的设置：填充样式的重载checkbox和填充样式
        void SetHatchPatternCell(int row, int column);
        // 旋转角度两列的显示： 旋转角度的重载checkbox和旋转角度
        void ShowRotateCell(GetDoubleFunc func, SetDoubleFunc setFunc, OverrideFunc overrideFunc, int row, int column);
        // 旋转角度两列的设置： 旋转角度的重载checkbox和旋转角度
        void SetRotateCell(int row, int column);
        // 缩放值两列的显示： 缩放值的重载checkbox和缩放值
        void ShowScaleCell(GetDoubleFunc func, SetDoubleFunc setFunc, OverrideFunc overrideFunc, int row, int column);
        // 缩放值两列的设置： 缩放值的重载checkbox和缩放值
        void SetScaleCell(int row, int column);

        // 显示文字
        void ShowTextCell(std::wstring text, int row, int column, bool isReadOnly = false);
        // 获得文字
        std::wstring GetTextCell(int row, int column);

        // 按照类别重载图形节点的cell设置
        // isEnabled：该cell是否可以修改
        void ShowCategoryCell(int row, int column, const gcmp::ICategory* pCurrentCategory, bool isEnabled);
        // 按照类别重载设置图形节点的样式到m_gOverrideDataList
        void SetCategoryCell(int row, int column);
    private:
        QDialog* m_parent;

        // 各种显示样式设置层级
        const std::vector<std::wstring> m_rowNames = { L"文档级类别", L"视图级类别", L"文档级图元：回调", L"视图级图元：回调",
            L"文档级图元节点：名称", L"文档级图元节点：类别", L"视图级图元节点：名称", L"视图级图元节点：类别", L"节点直接设置" };

        gcmp::WeakPtr<gcmp::IUiView> m_wpCurrentView;
        gcmp::WeakPtr<gcmp::IUiDocument> m_wpUIDoc;
        std::vector<std::wstring> m_hatchPatternNames;

        // 显示样式的数据，按照表格中的顺序排列
        std::vector<gcmp::OwnerPtr<GraphicsOverrideData>>& m_gOverrideDataList;

        static const int s_numStyleLines;
        static const int s_countLinePageColumns;
        static const int s_countFacePageColumns;

        QTableWidget* m_table;
        gcmp::OwnerPtr<QButtonGroup> m_opColorBtnGroup;      // 颜色按钮组
        gcmp::OwnerPtr<QButtonGroup> m_opLineTypeBtnGroup;   // 线型按钮组。
        std::map<UVIndex, QColor> m_colorMap;               // 颜色映射
    };
}

